package my.spring.aop;

import my.spring.aop.advice.Advice;
import my.spring.aop.advice.AfterAdvice;
import my.spring.aop.advice.BeforeAdvice;

import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;

/**
 * 使用动态代理实现AOP
 * @author fengbo
 * @date 2018/6/30
 */
public class JdkDynamicAopProxy implements AopProxy, InvocationHandler {

    private Advised advised;

    public JdkDynamicAopProxy(Advised advised) {
        this.advised = advised;
    }

    @Override
    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
        if (!advised.getAdvisor().getPointcut().getMethodMatcher().matches(method, advised.getTarget().getClass())) {
            return method.invoke(advised.getTarget(), args);
        }
        Advice advice = advised.getAdvisor().getAdvice();
        if (advice instanceof BeforeAdvice) {
            ((BeforeAdvice) advice).before(method, args, advised.getTarget());
        }
        Object result = method.invoke(advised.getTarget(), args);
        if (advice instanceof AfterAdvice) {
            ((AfterAdvice) advice).after(method, args, advised.getTarget());
        }
        return result;
    }

    @Override
    public Object getProxy() {
        return getProxy(Thread.currentThread().getContextClassLoader());
    }

    @Override
    public Object getProxy(ClassLoader classLoader) {
        return Proxy.newProxyInstance(classLoader, advised.getTarget().getClass().getInterfaces(), this);
    }
}
